#include <cmath>
#include <QDebug>
#include <QFontMetrics>
#include <QGuiApplication>
#include "element.h"

DrawParallelLine::DrawParallelLine(void)
{
    m_line1_start = QPoint(0, 0);
    m_line1_end = QPoint(0, 0);
    m_line2_start = QPoint(0, 0);
    m_line2_end = QPoint(0, 0);
    m_length = 0.0;
    m_distance = 0.0;
    m_cos_theta  = 1.0;
    m_sin_theta = 0.0;
    m_drawType = PARALLEL;
    m_state = Element::DS_IDLE;
}

inline void DrawParallelLine::setStartPoint(QPoint point)
{
    m_line1_start = point;
    m_line1_end = point;
    m_line2_start = point;
    m_line2_end = point;
    m_length = 0.0;

    m_state = Element::DS_STATE1; // 表明第一条线的起点已经确定，终点还没确定
}

inline void DrawParallelLine::setTempEndPoint(QPoint point)
{
    m_line1_end = point;
}
inline void DrawParallelLine::setEndPoint(QPoint point)
{
    m_line1_end = point;
    computeLengthSlope();
    m_state = Element::DS_STATE2; // 表示第一条线已经完全确定了
}
inline void DrawParallelLine::setSecondLine(QPoint point)
{
    m_line2_start.setX(point.x() - m_length / 2.0 * m_cos_theta);
    m_line2_start.setY(point.y() - m_length / 2.0 * m_sin_theta);
    m_line2_end.setX(point.x() + m_length / 2.0 * m_cos_theta);
    m_line2_end.setY(point.y() + m_length / 2.0 * m_sin_theta);

    m_state = Element::DS_FINISH; //  至此，平行线完全确定
    computeDist(); // 得到线段间的距离

    bool isCtrlPressed = QGuiApplication::keyboardModifiers() & Qt::ControlModifier;

    if(isCtrlPressed)
    {
        double f = -1.0;
        if(m_cos_theta != 0)
        {
            double m_tan_theta = m_sin_theta / m_cos_theta;
            double y = m_tan_theta * point.x() - m_tan_theta * m_line1_start.x() + m_line1_start.y();//判断第二条线相对第一条
            if(y > point.y())
            {
                f = -f;
            }
            if(m_cos_theta < 0)
            {
                f = -f;
            }
        }
        else
        {
            if(point.x() > m_line1_start.x())
            {
                f = -f;
            }
        }
        m_line2_start.setX(m_line1_start.x() + f *m_distance * m_sin_theta);
        m_line2_start.setY(m_line1_start.y() - f *m_distance * m_cos_theta);
        m_line2_end.setX(m_line1_end.x() + f *m_distance * m_sin_theta);
        m_line2_end.setY(m_line1_end.y() - f *m_distance * m_cos_theta);
    }

    int X = ( m_line1_start.x() + m_line1_end.x() +
              m_line2_start.x() + m_line2_end.x() ) / 4;
    int Y = ( m_line1_start.y() + m_line1_end.y() +
              m_line2_start.y() + m_line2_end.y() ) / 4;
    m_textBox.moveTo(X, Y);
    updateText();
}

void DrawParallelLine::build(QPoint p1, QPoint p2, QPoint p3)
{
    setStartPoint(p1);
    setEndPoint(p2);
    setSecondLine(p3);
}

inline void DrawParallelLine::setTempSecondLine(QPoint point)
{
    m_line2_start.setX(point.x() - m_length / 2.0 * m_cos_theta);
    m_line2_start.setY(point.y() - m_length / 2.0 * m_sin_theta);
    m_line2_end.setX(point.x() + m_length / 2.0 * m_cos_theta);
    m_line2_end.setY(point.y() + m_length / 2.0 * m_sin_theta);
    bool isCtrlPressed = QGuiApplication::keyboardModifiers() & Qt::ControlModifier;

    if(isCtrlPressed)
    {
        computeDist(); // 得到线段间的距离
        if(isCtrlPressed)
        {
            double f = -1.0;
            if(m_cos_theta != 0)
            {
                double m_tan_theta = m_sin_theta / m_cos_theta;
                double y = m_tan_theta * point.x() - m_tan_theta * m_line1_start.x() + m_line1_start.y();
                if(y > point.y())
                {
                    f = -f;
                }
                if(m_cos_theta < 0)
                {
                    f = -f;
                }
            }
            else
            {
                if(point.x() > m_line1_start.x())
                {
                    f = -f;
                }
            }
            m_line2_start.setX(m_line1_start.x() + f *m_distance * m_sin_theta);
            m_line2_start.setY(m_line1_start.y() - f *m_distance * m_cos_theta);
            m_line2_end.setX(m_line1_end.x() + f *m_distance * m_sin_theta);
            m_line2_end.setY(m_line1_end.y() - f *m_distance * m_cos_theta);
        }
    }
}

int	DrawParallelLine::mouseMove(QPoint point)
{
    bool isCtrlPressed = QGuiApplication::keyboardModifiers() & Qt::ControlModifier;

    if( m_state == Element::DS_STATE1 ) // 第一条线的终点还没确定, 这时鼠标左键肯定是按下的
    {
        if(isCtrlPressed)
        {
            QPoint tmp;
            if(abs(point.x() - m_line1_start.x()) > abs(point.y() - m_line1_start.y()))
            {
                tmp.setX(point.x());
                tmp.setY(m_line1_start.y());
            }
            else
            {
                tmp.setX(m_line1_start.x());
                tmp.setY(point.y());
            }
            setTempEndPoint(tmp);
        }
        else
        {
            setTempEndPoint(point);
        }
        return 1;
    }
    else if( m_state == Element::DS_STATE2 ) // 第一条线已经确定了，这里要确定第二条线。
    {
        setTempSecondLine(point);
        return 1;
    }
    return 0;
}

int	DrawParallelLine::mouseLButtonPress(QPoint point)
{
    if( m_state == Element::DS_IDLE ) // 第一条线的起点还没确定
    {
        setStartPoint(point);
        return 1;
    }
    else if( m_state == DS_STATE2 )
    {
        setSecondLine(point);
        return 1;
    }
    return 0;
}
int	DrawParallelLine::mouseLButtonRelease(QPoint point)
{
    bool isCtrlPressed = QGuiApplication::keyboardModifiers() & Qt::ControlModifier;


    if( m_state == Element::DS_STATE1 ) // // 表明第一条线的起点已经确定，终点还没确定
    {
        if(isCtrlPressed)
        {
            QPoint tmp;
            if(abs(point.x() - m_line1_start.x()) > abs(point.y() - m_line1_start.y()))
            {
                tmp.setX(point.x());
                tmp.setY(m_line1_start.y());
            }
            else
            {
                tmp.setX(m_line1_start.x());
                tmp.setY(point.y());
            }
            setEndPoint(tmp);
        }
        else
        {
            setEndPoint(point);
        }
        return 1;
    }
    return 0;
}

void DrawParallelLine::computeLengthSlope( void )
{
    m_length = hypot( m_line1_end.x() - m_line1_start.x(), m_line1_end.y() - m_line1_start.y() );
    if( m_line1_end.x() == m_line1_start.x() ) // 也包括了  m_length == 0 的情况，下面就不需要特殊处理了
    {
        m_cos_theta = 0.0;
        m_sin_theta  = 1.0;
    }
    else
    {
        m_cos_theta = ( m_line1_end.x() - m_line1_start.x() ) / m_length;
        m_sin_theta = ( m_line1_end.y() - m_line1_start.y() ) / m_length;
    }
}

void DrawParallelLine::computeDist(void)
{
    //两条直线的距离，可以转换为一点到一条直线的距离
    //点P(X,Y)到直线Ax+By+C=0的距离为          |AX+BY+C|  除以 根号下(A^2+B^2)
    //直线公式(x-x1)/(x2-x1)=(y-y1)/(y2-y1)--》(y2-y1)x+(x1-x2)y-x1(y2-y1)+y1(x2-x1)=0
    //////////////////////////////////////////////////////////////////////////
    double A = m_line1_end.y() - m_line1_start.y();
    double B = m_line1_start.x() - m_line1_end.x();
    double C = - m_line1_start.x() * A - m_line1_start.y() * B;

    m_distance = abs(A * m_line2_start.x() + B * m_line2_start.y() + C ) / hypot(A, B);
}

void DrawParallelLine::updateText(void)
{
    //m_text = QString(tr("D = %1 um")).arg(m_distance * m_scale, 2, 'f', 2);
    if(m_distance * m_scale >= 1000.0)
    {
        m_text = QString::fromUtf8(u8"L = %1 mm").arg(m_distance * m_scale / 1000.0, 2, 'f', 2);
    }
    else
    {
        m_text = QString::fromUtf8(u8"L = %1 μm").arg(m_distance * m_scale, 2, 'f', 2);
    }
    QFontMetrics fm(m_textFont);
    int textWidth = fm.width(m_text);
    int textHeight = fm.height();
    m_textBox.setWidth(textWidth);
    m_textBox.setHeight(textHeight);
}

void DrawParallelLine::computeBox(void)
{
    int min1_x, max1_x, min1_y, max1_y;
    int min2_x, max2_x, min2_y, max2_y;
    int min_x, max_x, min_y, max_y;

    min1_x = qMin(m_line1_start.x(), m_line1_end.x());
    max1_x = qMax(m_line1_start.x(), m_line1_end.x());
    min1_y = qMin(m_line1_start.y(), m_line1_end.y());
    max1_y = qMax(m_line1_start.y(), m_line1_end.y());

    min2_x = qMin(m_line2_start.x(), m_line2_end.x());
    max2_x = qMax(m_line2_start.x(), m_line2_end.x());
    min2_y = qMin(m_line2_start.y(), m_line2_end.y());
    max2_y = qMax(m_line2_start.y(), m_line2_end.y());

    min_x = qMin(min1_x, min2_x);
    max_x = qMax(max1_x, max2_x);
    min_y = qMin(min1_y, min2_y);
    max_y = qMax(max1_y, max2_y);
    qDebug() << min_x << ", " << min_y << ", " << max_x << ", " << max_y;
    qDebug() << "line1 = " << m_line1_start << ", " << m_line1_end;
    qDebug() << "line2 = " << m_line2_start << ", " << m_line2_end;
    m_box.setCoords ( min_x, min_y, max_x, max_y );
}

void DrawParallelLine::draw( QPainter &painter )
{
    if(m_state != Element::DS_IDLE)
    {
        painter.save();
        painter.setPen(m_linePen);
        painter.drawLine ( m_line1_start, m_line1_end );
        if(m_state == Element::DS_STATE2 )
        {
            painter.drawLine ( m_line2_start, m_line2_end );
        }
        else if( m_state == Element::DS_FINISH )
        {
            painter.drawLine ( m_line2_start, m_line2_end );
            painter.setFont(m_textFont);
            painter.drawText(m_textBox, m_text);
        }
        painter.restore();
    }
}
